#ifndef _SCIENCE_MATHEMATICS_NUMBERS_Whole_INCLUDED_H_
#define _SCIENCE_MATHEMATICS_NUMBERS_Whole_INCLUDED_H_

#include <string>
#include <map>

#ifdef MATHEMATICS_EXPORTS
#define MATHEMATICS_API __declspec(dllexport)
#else
#define MATHEMATICS_API __declspec(dllimport)
#endif

namespace Science
{
	namespace Mathematics
	{
		namespace Numbers
		{
			// the type of the digit
			typedef unsigned char digit;

			// This class represent the whole number in numbering system of Mathematics
			class MATHEMATICS_API Whole
			{

			public:

				// the list of digits
				typedef std::pair<unsigned __int64, digit> Digit;
				typedef std::map<unsigned __int64, digit> DigitList;
				typedef std::map<unsigned __int64, digit>::iterator DigitIterator;

			private:

				// the place and digit for the number
				DigitList _number;

			public:

				// Whole default constructor that initialize the whole number with 0
				Whole();

				// Whole constructor that copy the src whole number to the current
				// object
				Whole(const Whole& pSrc);

				// Whole constructor that moves the contents of the src whole number to the
				// current object
				Whole(Whole&& pSrc);

				// Whole constructor that initialize the whole number with data stream
				Whole(unsigned __int64 pNum);

				// Whole constructor that initialize the whole number with data string
				Whole(std::string numStr);

				// Whole destructor that free the number stream
				~Whole();

			public:

				// convert the whole number to unsigned int 64
				operator unsigned __int64();								

				// Assignement operator that assign the src value to the current object
				Whole& operator=(const Whole& pSrc);

				// Assignement operator that assign the src value to the current object
				Whole& operator=(unsigned __int64 numStr);

				// Assignement operator that assign the src value to the current object
				Whole& operator=(std::string numStr);

				// Assignement operator that move the src value to the current object
				Whole& operator=(Whole&& pSrc);

				// Compare two whole number if they are equal				
				bool operator==(const Whole& rhs);

				// Compare two whole number if they are less than
				bool operator<(const Whole& rhs);

				// Compare two whole number if they are greater than
				bool operator>(const Whole& rhs);

				// Compare two whole number if they are not equal
				bool operator!=(const Whole& rhs);

				// Compare two whole number if they are less than or equal
				bool operator<=(const Whole& rhs);

				// Compare two whole number if they are greater than or equal
				bool operator>=(const Whole& rhs);	

				// Add two numbers
				Whole operator+(const Whole& rhs);
				Whole operator+(unsigned __int64 numStr);
				Whole operator+(std::string numStr);
				Whole& operator+=(const Whole& rhs);
				Whole& operator+=(unsigned __int64 numStr);
				Whole& operator+=(std::string numStr);

			public:

				// get the digit with the supplied place value
				unsigned char getPlaceValue(unsigned __int64 place);

				// round the number to the nearest supplied place
				Whole round(unsigned __int64 place = 1);

			public:

				// convert the number to string
				std::string toString();

			private:

				// parse the unsigned int to its raw values
				void parseNum(unsigned __int64 num);

				// parse the string to its raw values
				void parseNum(std::string num);

				// get the unsigend __int64 value
				unsigned __int64 getValue() const;
			};
		}
	}
}

#endif


